package cn.demoxy.service.impl;

import cn.demoxy.service.DemoServerConfService;
import cn.demoxy.utils.Arith;
import cn.demoxy.utils.IpUtils;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @auther demo
 * @date 2022/6/8 14:52
 */
@Service
public class DemoServerConfServiceImpl implements DemoServerConfService {
    @SneakyThrows
    @Override
    public Map<String, Object> findAllServerConf() {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> cpuList = new ArrayList<>();
        List<Map<String, Object>> serverList = new ArrayList<>();
        List<Map<String, Object>> javaList = new ArrayList<>();
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();
        CentralProcessor processor = hal.getProcessor();
        // CPU信息
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        //这里不休眠的话获取不到cpu信息
        Util.sleep(1000);
        long[] ticks = processor.getSystemCpuLoadTicks();
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;

        GlobalMemory memory = hal.getMemory();
        Map<String, Object> cpuMap = new HashMap<>();
        cpuMap.put("cpuKey","用户使用率");
//        cpuMap.put("value",user);
        double user_d = user;
        cpuMap.put("value",Arith.round(Arith.mul(user_d / totalCpu, 100), 2)+"%");
        cpuMap.put("sizeKey","总内存");
        cpuMap.put("size",Arith.div(memory.getTotal(), (1024 * 1024 * 1024), 2)+"GB");
        Runtime r = Runtime.getRuntime();
        cpuMap.put("jvm", Arith.div(r.totalMemory(), (1024 * 1024), 2)+"MB");
        cpuList.add(cpuMap);
        Map<String, Object> cpuMap1 = new HashMap<>();
        cpuMap1.put("cpuKey","系统使用率");
        double sys_d = cSys;
        cpuMap1.put("value",Arith.round(Arith.mul(sys_d / totalCpu, 100), 2)+"%");
        cpuMap1.put("sizeKey","已用内存");
        cpuMap1.put("size",Arith.div(memory.getTotal() - memory.getAvailable(), (1024 * 1024 * 1024), 2)+"GB");
        cpuMap1.put("jvm", Arith.div(r.totalMemory()-r.freeMemory(), (1024 * 1024), 2)+"MB");
        cpuList.add(cpuMap1);
        Map<String, Object> cpuMap2 = new HashMap<>();
        cpuMap2.put("cpuKey","当前空闲率");
        double free_d = idle;
        cpuMap2.put("value",Arith.round(Arith.mul(free_d / totalCpu, 100), 2)+"%");
        cpuMap2.put("sizeKey","剩余内存");
        cpuMap2.put("size", Arith.div( memory.getAvailable(), (1024 * 1024 * 1024), 2)+"GB");
        cpuMap2.put("jvm", Arith.div(r.freeMemory(), (1024 * 1024), 2)+"MB");
        cpuList.add(cpuMap2);

        Map<String, Object> serverMap = new HashMap<>();
        serverMap.put("serverKey","服务器IP");
        serverMap.put("serverValue",InetAddress.getLocalHost().getHostAddress());
        serverMap.put("serverKey1","操作系统");
        Properties props = System.getProperties();
        serverMap.put("serverValue1",props.getProperty("os.name"));
        serverList.add(serverMap);
        Map<String, Object> serverMap1 = new HashMap<>();
        serverMap1.put("serverKey","系统所在位置");
        serverMap1.put("serverValue", props.getProperty("user.dir"));
        serverMap1.put("serverKey1","系统架构");
        serverMap1.put("serverValue1",props.getProperty("os.arch"));
        serverList.add(serverMap1);

        Map<String, Object> javaMap = new HashMap<>();
        javaMap.put("javaKey","java名称");
        javaMap.put("javaValue",props.getProperty("java.specification.name"));
        javaMap.put("javaKey1","Java版本");
        javaMap.put("javaValue1",props.getProperty("java.specification.version"));
        javaList.add(javaMap);
        Map<String, Object> javaMap1 = new HashMap<>();
        javaMap1.put("javaKey","启动时间");
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        Date date = new Date();
        date.setTime(time);
        javaMap1.put("javaValue",new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss").format(date) );
        javaMap1.put("javaKey1","运行时长");
        javaMap1.put("javaValue1",timeStampToDhms(System.currentTimeMillis()-time));
        javaList.add(javaMap1);
        Map<String, Object> javaMap2 = new HashMap<>();
        javaMap2.put("javaKey","java安装路径");
        javaMap2.put("javaValue",props.getProperty("java.home"));
        javaList.add(javaMap2);



        List<Map<String, Object>> dirs = new ArrayList<>();
        OperatingSystem os = si.getOperatingSystem();
        FileSystem fileSystem = os.getFileSystem();
        List<OSFileStore> fsArray = fileSystem.getFileStores();
        for (OSFileStore fs : fsArray) {
            long free = fs.getUsableSpace();
            long total = fs.getTotalSpace();
            long used = total - free;
            Map<String, Object> sysFile = new HashMap();
            sysFile.put("name", fs.getMount());
            sysFile.put("SysTypeName", fs.getType());
            sysFile.put("type", fs.getName());
            sysFile.put("allSize",convertFileSize(total));
            sysFile.put("freeSize", convertFileSize(free));
            sysFile.put("useSize",convertFileSize(used));
            sysFile.put("use", Arith.mul(Arith.div(used, total, 4), 100)+"%");

            dirs.add( sysFile);
        }
        result.put("dir",dirs);
        result.put("cpuList",cpuList);
        result.put("serverList",serverList);
        result.put("javaList",javaList);
        return result;
    }
    // 毫秒时间戳转换为日、时、分、秒
    public static String timeStampToDhms(long milliseconds) {
        long day = TimeUnit.MILLISECONDS.toDays(milliseconds);
        long hours = TimeUnit.MILLISECONDS.toHours(milliseconds) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(milliseconds));
        long minutes = TimeUnit.MILLISECONDS.toMinutes(milliseconds) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milliseconds));
        long seconds = TimeUnit.MILLISECONDS.toSeconds(milliseconds) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliseconds));
        StringBuilder sb = new StringBuilder();
        if (day != 0) {
            sb.append(day + "天");
        }
        sb.append(hours + "小时");
        sb.append(minutes + "分");
        sb.append(seconds + "秒");
        return sb.toString();
    }

    /**
     * 字节转换
     *
     * @param size 字节大小
     * @return 转换后值
     */
    public static String convertFileSize(long size) {
        long kb = 1024;
        long mb = kb * 1024;
        long gb = mb * 1024;
        if (size >= gb) {
            return String.format("%.1f GB", (float) size / gb);
        } else if (size >= mb) {
            float f = (float) size / mb;
            return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
        } else if (size >= kb) {
            float f = (float) size / kb;
            return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
        } else {
            return String.format("%d B", size);
        }
    }
}
